home *** CD-ROM | disk | FTP | other *** search
- /*
- File: PGPUAMclient.c
-
- Description: PGP Appleshare User Authentication Module
-
- Written by: Vinnie Moscaritolo
-
- Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- //------------------------------------------------------------------------------------
- #pragma mark Includes
- //------------------------------------------------------------------------------------
- #include <Errors.h>
- #include <String.h>
- #include <A4Stuff.h>
- #include <Resources.h>
- #include <MixedMode.h>
- #include <Appearance.h>
- #include <CodeFragments.h>
- #include <Gestalt.h>
- #include <PLStringFuncs.h>
-
- #include "ClientUAM.h"
- #include "AFPPackets.h"
-
- #include <stdio.h>
-
- #include "TPGPkey.h"
- #include "TPGPException.h"
- #include "TMacException.h"
- #include "TASIPPGPkey.h"
- #include "ASIPChallenge.h"
- #include "PGPUAMdefines.h"
- #include "PGPUAMclient.h"
- #include "PGPUAMclientLoginDialog.h"
- #include "PGPUAMclientProtocol.h"
- #include "PGPUAMmsgFormat.h"
- #include "PGPUAMclient.h"
- #include "TPGPUAMPrefs.h"
- #include "pgpUserInterface.h"
-
-
-
- // ---------------------------------------------------------------------------
- #pragma mark Exported Symbols
- // ---------------------------------------------------------------------------
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- #pragma export on
- extern const long __procinfo = kUAMCallProcInfo;
- OSErr __pgpuam_initialize(CFragInitBlockPtr ibp);
- void __pgpuam_terminate(void);
- pascal OSStatus __pgpuam_client (UAMArgs *theArgs);
-
- pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
- pascal OSErr __terminate(void);
- #pragma export off
-
-
- #ifdef __cplusplus
- }
- #endif
-
-
- // ---------------------------------------------------------------------------
- #pragma mark Globals
- // ---------------------------------------------------------------------------
- AFPSrvrInfo * gAFPServerInfo = nil;
- AFPClientInfo * gClientInfo = nil;
- UInt8 * gAFPSrvrSig = nil;
-
- // ---------------------------------------------------------------------------
- #pragma mark Local Prototypes
- // ---------------------------------------------------------------------------
-
- static OSStatus PGPUAMOpen (UAMArgs *theArgs);
- static OSStatus PGPUAMClose (UAMArgs *theArgs);
- static OSStatus PGPUAMLogin (UAMArgs *theArgs);
-
-
- static OSStatus InitiateConnection (StringPtr userName,
- StringPtr serverName,
- short *sessionRefNum,
- TPGPUAMPrefs *userPrefs,
- TASIPPGPkey *serverKey,
- IdleConnectionProcPtr idleProc,
- void* context );
-
- static void TerminateConnection (void* context);
-
- static StringPtr FigureAFPVersion( AFPSrvrInfo *info,ClientUAMCallbackRec *callbacks);
- static Boolean FindStringInBuf( StringPtr string, Ptr buf, UInt32 bufSize);
-
- static void PostError(short errorStrId, short explanStrID);
-
- // test code..
-
- // ---------------------------------------------------------------------------
- OSErr __pgpuam_initialize(CFragInitBlockPtr ibp)
- // ---------------------------------------------------------------------------
- //
- // PGPUAM Library Initialization
- //
-
- {
- long gestaltResult;
- OSErr err = -1;
-
- /*
- ** Check for a 68020 or later processor and bail immediately if
- ** none is available.
- */
- //DebugStr("\p__pgpuam_initialize");
-
- if( Gestalt( gestaltProcessorType, &gestaltResult ) == noErr &&
- gestaltResult >= gestalt68020 )
- {
- err = __initialize( ibp );
- }
-
- return err;
- }
-
-
- // ---------------------------------------------------------------------------
- void __pgpuam_terminate(void)
- // ---------------------------------------------------------------------------
- //
- // PGPUAM Library Termination
- //
-
- {
- __terminate();
- }
-
-
- #pragma mark -
- // ---------------------------------------------------------------------------
- pascal OSStatus __pgpuam_client(UAMArgs *theArgs)
- // ---------------------------------------------------------------------------
- {
- OSStatus error;
- char errorBuf[256];
- char explanationBuf[256];
- // ostrstream err( errorBuf,256);
- // ostrstream explain( explanationBuf,256);
-
- EnterCodeResource();
- try
- {
- switch(theArgs->command)
- {
- case kUAMOpen:
- // DebugStr("\pUAMCall - kUAMOpen");
- error = PGPUAMOpen(theArgs);
- break;
-
- case kUAMPWDlog:
- // DebugStr("\pUAMCall - kUAMPWDlog");
- error = noErr;
- break;
-
- case kUAMLogin:
- // DebugStr("\pUAMCall - kUAMLogin");
- error = PGPUAMLogin(theArgs);
- break;
-
- case kUAMVSDlog:
- // DebugStr("\pUAMCall - kUAMVSDlog");
- error = noErr;
- break;
-
- case kUAMChgPassDlg:
- DebugStr("\pUAMCall - kUAMChgPassDlg");
- error = kNotForUs;
- break;
-
- case kUAMChgPass:
- DebugStr("\pUAMCall - kUAMChgPass");
- error = kNotForUs;
- break;
-
- case kUAMGetInfoSize:
- DebugStr("\pUAMCall - kUAMGetInfoSize");
- // uamInfoSize = n;
- error = kNotForUs;
- break;
-
- case kUAMGetInfo:
- DebugStr("\pUAMCall - kUAMGetInfo");
- // uamInfo < ==
- error = kNotForUs;
- break;
-
- case kUAMClose:
- // DebugStr("\pUAMCall - kUAMClose");
- error = PGPUAMClose(theArgs);
- break;
-
- default:
- DebugStr("\psome other UAMCall");
- error = kNotForUs;
- break;
- }
- }
- catch (TMacException &ex)
- {
- SInt16 itemHit;
-
- error = theArgs->result = ex.GetExceptionErr();
- if(error == noErr)
- error = userCanceledErr;
-
- errorBuf[0] = sprintf(&errorBuf[1], "%s\rPGPUAM Error: %d\rFile: %s, Line: %d",
- ex.GetExceptionMessage(), ex.GetExceptionErr(), ex.GetExceptionFile(), ex.GetExceptionLine());
-
- StandardAlert(kAlertStopAlert,"\pThe PGP Challenge/Response UAM could not be used.",
- (UInt8 *) errorBuf, nil , &itemHit);
- }
-
- // handle PGP errors
- catch (TPGPException &ex)
- {
- SInt16 itemHit;
- PGPGetErrorString ( ex.GetExceptionErr(), sizeof(explanationBuf), explanationBuf);
-
- errorBuf[0] = sprintf(&errorBuf[1], "%s\r\rPGPUAM Error: %d\rFile: %s, Line: %d",
- ex.GetExceptionMessage(), ex.GetExceptionErr(), ex.GetExceptionFile(), ex.GetExceptionLine());
-
- c2pstr(explanationBuf);
- StandardAlert(kAlertStopAlert,(UInt8 *)errorBuf, (UInt8 *)explanationBuf, nil , &itemHit);
- error = theArgs->result = userCanceledErr;
- }
-
- ExitCodeResource();
- return error;
- }
-
- // ---------------------------------------------------------------------------
- static OSStatus PGPUAMOpen(UAMArgs *theArgs)
- // ---------------------------------------------------------------------------
- {
- OSStatus ErrNo ;
- long response = 0;
-
- // Get the AppleShare Client info
- ErrNo = CallUniversalProc( theArgs->callbacks->GetClientInfoUPP, kGetClientInfoProcInfo, kAFPClientInfo, &gClientInfo);
- if(ErrNo != noErr) return ErrNo;
-
- // check agaisnt client versions
- ThrowMsgIfNot ( (gClientInfo->fVersion > 8),
- "This UAM requires AppleShare Client 3.8.1 or later");
-
- // Save the server info pointer.
- gAFPServerInfo = theArgs->Opt.open.srvrInfo;
-
- // calculate server signature block.
- UInt8 *signatureOffset;
- signatureOffset = (&gAFPServerInfo->fSrvrName[0] + gAFPServerInfo->fSrvrName[0] + 1);
- if ( (UInt32)signatureOffset & 0x01) signatureOffset++;
- gAFPSrvrSig = ((UInt8*) gAFPServerInfo) + * ((short*)signatureOffset);
-
- // Is Appearance Mgr available ?
- ThrowMsgIfNot ( ((Gestalt(gestaltAppearanceAttr, &response) == noErr)
- && ((long)RegisterAppearanceClient != kUnresolvedCFragSymbolAddress)) ,
- "Appearance Mgr is required");
-
- // collection manager too
- ThrowMsgIfNot ( ((Gestalt(gestaltCollectionMgrVersion, &response) == noErr)
- && ((long)NewCollection != kUnresolvedCFragSymbolAddress)) ,
- "Collection Mgr is required");
-
- // Is PGPsdk available ?
- ThrowMsgIfNot ((long)PGPNewContext != kUnresolvedCFragSymbolAddress,
- "PGPsdk is required");
-
- // Is PGPsdkUIlib available ?
- ThrowMsgIfNot ((long)PGPSigningPassphraseDialog != kUnresolvedCFragSymbolAddress ,
- "PGPsdkUIlib is required");
-
- // Create a new PGP context
- TPGPkey::Initialize();
-
- // establish link to PassphraseCache
- //???
-
- theArgs->result = ((1 << kUsePWDlog) | (1 << kUseUAMInfo)) ;
- return noErr;
- }
-
- // ---------------------------------------------------------------------------
- static OSStatus PGPUAMLogin(UAMArgs *theArgs)
- // ---------------------------------------------------------------------------
- {
- TPGPUAMPrefs* userPrefs = nil;
- Str63 userName;
-
- // Get user prefs
- userPrefs = new TPGPUAMPrefs();
- userPrefs->Initialize();
-
- // open the keyring
- TPGPkey::OpenKeyDefaultRing();
-
- // if no username was specified.. (Alias resolution)
- // Initiate the connection w/o UI
- if(theArgs->Opt.auth.userName[0] != '\0')
- {
- TASIPPGPkey theServerKey;
-
- // copy the user name from the authblock
- PLstrcpy( userName, theArgs->Opt.auth.userName);
-
-
- // pickup the server key
- theServerKey.Initialize(gAFPSrvrSig);
-
- // initiate connection directly
- theArgs->result = InitiateConnection(userName, gAFPServerInfo->fSrvrName, &theArgs->sessionRefNum, userPrefs, &theServerKey, nil, theArgs);
-
- }
- else
- {
- // copy the default user name.
- PLstrcpy( userName, gClientInfo->fDefaultUserName);
-
- // initiate connection with User Interface
- theArgs->result = DoLoginDialog( userName,
- gAFPServerInfo->fSrvrName,
- &theArgs->sessionRefNum,
- userPrefs,
- InitiateConnection,
- TerminateConnection,
- theArgs->callbacks->EventCallbackUPP,
- theArgs);
-
- // put username into the authblock buffer for later Alias resolution
- PLstrcpy(theArgs->Opt.auth.userName, userName);
-
- // not clear if I should post the error or not
- // you might want to take out the next line...
- if(( theArgs->result != noErr) && (theArgs->result != userCanceledErr))
- PostError( kErrOther, kErrOtherExplanation);
- }
-
- // close the keyring
- TPGPkey::CloseKeyRing();
-
- // update user prefs
- userPrefs->Finalize();
- delete userPrefs;
-
- return (theArgs->result) ;
- }
-
- // ---------------------------------------------------------------------------
- static OSStatus PGPUAMClose(UAMArgs *theArgs)
- // ---------------------------------------------------------------------------
- {
-
- // remove PGP context
- TPGPkey::Finalize();
-
- return noErr;
- }
-
- #pragma mark -
-
-
- // ---------------------------------------------------------------------------
- static OSStatus InitiateConnection( StringPtr userName,
- StringPtr serverName,
- short *sessionRefNum,
- TPGPUAMPrefs *userPrefs,
- TASIPPGPkey *serverKey,
- IdleConnectionProcPtr idleProc,
- void* context)
- // ---------------------------------------------------------------------------
- {
- UAMArgs *theArgs = (UAMArgs *) context;
- PUAM_LOGIN_RESP resp;
- StringPtr serverVersion;
- Str63 challengeString;
- Str63 answerString;
- Str255 promptString;
-
- UInt8 replyBuffer[256];
- UInt32 replyBufferSize;
- Handle uamName;
- OSStatus ErrNo ;
-
- // calculate which AFPversion we will use.
- serverVersion = FigureAFPVersion(gAFPServerInfo,theArgs->callbacks);
- if(!serverVersion){
- // put up an alert & return userCancelled error
- DebugStr("\pno AFP version returned by server");
- return userCanceledErr;
- }
-
- // get the UAMSTring from the resource
- uamName = Get1Resource(kUAMStr,kUAMProtoName);
- ThrowMacErrIfNil(uamName, ResError());
-
- // Calculate Challenge String
- MakeChallenge(serverKey, challengeString);
-
- // send OpenSession command to server.
- HLock(uamName);
- ErrNo = SndLoginCmd( theArgs->callbacks,
- serverVersion, (StringPtr) *uamName, userName,
- challengeString,
- theArgs->Opt.auth.srvrAddress,
- replyBuffer, sizeof (replyBuffer), &replyBufferSize,
- sessionRefNum,
- idleProc);
- HUnlock(uamName);
- if( ErrNo != kFPAuthContinue ) return ErrNo;
- ErrNo = userCanceledErr;
-
- // parse the reply
- ParseLoginResp(replyBuffer, &replyBufferSize, &resp);
-
- // check the reply
- if( ! VerifyChallenge(serverKey, challengeString, resp.CounterChallengePString))
- {
-
- // warn user that server didnt check out!
- Str255 errorBuf, explainBuf;
- SInt16 itemHit;
- AlertStdAlertParamRec aRec;
-
- aRec.movable = true;
- aRec.helpButton = false;
- aRec.filterProc = nil;
- aRec.defaultText = userPrefs->GetAuthenticateServer()? (unsigned char*) -1 : "\pAbort";
- aRec.cancelText = userPrefs->GetAuthenticateServer()? nil:"\pContinue";
- aRec.otherText = nil;
- aRec.defaultButton = kAlertStdAlertOKButton;
- aRec.cancelButton = kAlertStdAlertCancelButton;
- aRec.position = kWindowAlertPositionParentWindowScreen;
-
- GetIndString(errorBuf, kErrorStringsID, kErrUnableToAuthErr);
- PLstrcat(errorBuf, "\p\"");
- PLstrcat(errorBuf, serverName);
- PLstrcat(errorBuf, "\p\".");
- GetIndString(explainBuf, kErrorStringsID, userPrefs->GetAuthenticateServer() ? kErrUnableToAuthExplanation: kErrUnableToAuthContinueExplanation);
-
- StandardAlert(kAlertCautionAlert, errorBuf, explainBuf, &aRec , &itemHit);
-
- if(itemHit == kAlertStdAlertOKButton) return userCanceledErr;
- };
-
- // build custom prompt string
- PLstrcpy(promptString, "\pTo connect to \"");
- PLstrcat(promptString, serverName);
- PLstrcat(promptString, "\p\", please enter the passphrase for the following key.");
- p2cstr(promptString);
-
- ErrNo = ReplyToCounterChallenge(promptString, resp.FingerPrintPString, resp.CounterChallengePString, answerString);
- if(ErrNo == userCanceledErr) return ErrNo;
-
- if(ErrNo != noErr)
- {
- PostError(kErrClientUnableToAuthErr, kErrClientUnableToAuthExplanation);
- return userCanceledErr;
- }
-
- ErrNo = SndLoginContinueCmd(theArgs->callbacks, *sessionRefNum, answerString,
- replyBuffer, sizeof (replyBuffer), &replyBufferSize, idleProc);
-
- return ErrNo;
- }
-
-
-
- // ---------------------------------------------------------------------------
- static void PostError(short errorStrId,short explanStrID)
- // ---------------------------------------------------------------------------
- //
- {
- Str255 errorBuf, explainBuf;
- SInt16 itemHit;
-
- GetIndString(errorBuf, kErrorStringsID, errorStrId);
-
- if(explanStrID)
- GetIndString(explainBuf, kErrorStringsID, explanStrID);
-
- StandardAlert(kAlertStopAlert,errorBuf, (explanStrID)?explainBuf:nil, nil , &itemHit);
- }
-
- // ---------------------------------------------------------------------------
- static void TerminateConnection(void* context)
- // ---------------------------------------------------------------------------
- {
- UAMArgs *theArgs = (UAMArgs *) context;
-
- }
-
- #pragma mark -
-
- // ---------------------------------------------------------------------------
- static StringPtr FigureAFPVersion(AFPSrvrInfo *info,ClientUAMCallbackRec *callbacks)
- // ---------------------------------------------------------------------------
- {
- struct AFPClientInfo *theClientInfo = nil;
- short index;
- Ptr versBuf;
- UInt32 versBufsize;
-
- #if 0
- // Hack
- return "\pAFP TEST VERSION";
- // Hack
- #endif
-
- //DebugStr("\pFigureAFPVersion");
-
- CallUniversalProc( callbacks->GetClientInfoUPP, kGetClientInfoProcInfo, kAFPClientInfo, &theClientInfo);
-
- if(theClientInfo){
- // go through the list of AFP versions supported and try to find them
- // in the SrvrInfoBuffer, first match gets it
- versBuf = (Ptr)((UInt32)info + info->fVerCountOffset+1);
- versBufsize = kMaxAFPCommand - info->fVerCountOffset; // the largest size
-
- for(index = 0; index < theClientInfo->fNumAFPVersions; index++){
- if(FindStringInBuf(theClientInfo->fAFPVersionStrs[index],versBuf,versBufsize)){
- return theClientInfo->fAFPVersionStrs[index];
- }
- }
- }
- return nil;
- }
-
- // ---------------------------------------------------------------------------
- static Boolean FindStringInBuf(StringPtr string, Ptr buf, UInt32 bufSize)
- // ---------------------------------------------------------------------------
- {
- Ptr end = buf + bufSize;
- Byte len = string[0] + 1;
- short index;
-
- while((buf < end) && (*buf++ != string[0])) ; // scan for the proper length
-
- if(!(buf < end)){
- return false;
- }
- for(index = 1; (index < len) && (buf > end); index++){
- if(*buf++ != string[index])
- return false;
- }
- if(!(buf < end)){
- return false;
- }
- return true;
- }
-
-
-
-
-
-